<template>
  <div class="data-table" :style="style">
    <div :class="'table-header ' + classObject.tableHeader">
      <div
        :class="'header-col ' + classObject.headerCol"
        v-for="(item, index) in widget.option.header.data"
        :key="index"
        :style="item | filterColWidthStyle(widget.option.header.data)"
      >
        {{ item.label }}
      </div>
    </div>
    <div class="table-body">
      <div
        :class="'body-row ' + classObject.bodyRow"
        v-for="(row, rowIndex) in widget.option.body.data"
        :key="rowIndex"
      >
        <div
          :class="'body-col ' + classObject.bodyCol"
          v-for="(col, colIndex) in widget.option.header.data"
          :key="rowIndex + '-' + colIndex"
          :style="col | filterColWidthStyle(widget.option.header.data)"
        >
          {{ row[col.key] }}
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import { renderWidgetData } from "../tools/DataUtils";
export default {
  props: {
    widget: {
      type: [Object],
      default: () => {},
    },
  },
  data() {
    return {
      firstRow: 0,
      scrollTimer: null,
      render: null,
    };
  },
  computed: {
    classObject() {
      return {
        tableHeader: "table-header-" + this.widget.id,
        headerCol: "header-col-" + this.widget.id,
        bodyRow: "body-row-" + this.widget.id,
        bodyCol: "body-col-" + this.widget.id,
      };
    },
    style() {
      return {
        width: this.widget.location.width + "px",
        height: this.widget.location.height + "px",
        border: "1px solid " + this.widget.option.borderColor,
      };
    },
    data() {
      return this.widget.data;
    },
    rowHeightStyle() {
      return this.widget.location.height;
    },
    headerProps() {
      return {
        color: this.widget.option.header.color,
        fontSize: this.widget.option.header.fontSize,
        fontWeight: this.widget.option.header.fontWeight,
        backgroundColor: this.widget.option.header.backgroundColor,
      };
    },
    bodyProps() {
      return {
        color: this.widget.option.body.color,
        fontSize: this.widget.option.body.fontSize,
        fontWeight: this.widget.option.body.fontWeight,
        oddBackgroundColor: this.widget.option.body.oddBackgroundColor,
        evenBackgroundColor: this.widget.option.body.evenBackgroundColor,
      };
    },
    borderProps() {
      return this.widget.option.borderColor;
    },
    rowNumberProps() {
      return this.widget.option.rowNumber;
    },
    scrollProps() {
      return this.widget.option.scroll;
    },
    dynamicHeader() {
      return this.widget.option.header.data.length;
    },
    refresh() {
      return this.widget.service.timestamp;
    },
  },
  watch: {
    rowHeightStyle: {
      handler(widgetHeight) {
        this.refreshRowHeightStyle(widgetHeight);
      },
    },
    headerProps: {
      handler() {
        this.refreshHeaderStyle();
      },
      deep: true,
    },
    bodyProps: {
      handler() {
        this.refreshBodyStyle();
      },
      deep: true,
    },
    borderProps: {
      handler() {
        this.refreshTableBorderStyle();
      },
    },
    rowNumberProps: {
      handler() {
        // 改变显示的行数时，要重置滚动的设置
        this.widget.option.scroll.enable = false;
        this.refreshRowHeightStyle();
      },
    },
    scrollProps: {
      handler() {
        this.startScrollTableTimer();
      },
      deep: true,
    },
    dynamicHeader: {
      handler() {
        this.$nextTick(() => {
          this.refreshHeaderStyle();
          this.refreshBodyStyle();
          this.refreshTableBorderStyle();
        });
      },
    },
    data: {
      handler() {
        this.refreshWidgetInfo();
        this.$nextTick(() => {
          this.refreshHeaderStyle();
          this.refreshBodyStyle();
          this.refreshTableBorderStyle();
        });
      },
      deep: true,
    },
    refresh: {
      handler() {
        this.refreshWidgetInfo();
      },
    },
  },
  filters: {
    filterColWidthStyle(item, header) {
      // 未知宽度的列的计数器
      let number = 0;
      // 已知宽度的百分比
      let knownPercent = 0;
      for (let i = 0; i < header.length; i++) {
        let headerCol = header[i];
        if (headerCol.width) {
          knownPercent += Number(headerCol.width.replace("%", ""));
        } else {
          number += 1;
        }
      }
      let width = "";
      if (item.width || number === 0) {
        width = item.width;
      } else if (knownPercent > 100) {
        // 如果已知的宽度百分比大于100，则不设置宽度
        width = "";
      } else {
        width = (100 - knownPercent) / number + "%";
      }
      let style = {};
      style.width = width;
      return style;
    },
  },
  mounted() {
    this.refreshWidgetInfo();
    this.$nextTick(() => {
      this.refreshRowHeightStyle();
      this.refreshHeaderStyle();
      this.refreshBodyStyle();
      this.refreshTableBorderStyle();
      this.startScrollTableTimer();
    });
  },
  destroyed() {
    this.clearScrollTimer();
    this.recoveryRenderObject();
  },
  methods: {
    refreshWidgetInfo() {
      this.recoveryRenderObject();
      this.render = renderWidgetData(this.widget, this.renderEchartInfo);
    },
    renderEchartInfo(data) {
      this.widget.option.body.data = data;
      this.$nextTick(() => {
        this.recoveryTableData();
        this.refreshRowHeightStyle();
        this.refreshHeaderStyle();
        this.refreshBodyStyle();
        this.refreshTableBorderStyle();
      });
    },
    getTableHeader() {
      return document.getElementsByClassName(this.classObject.tableHeader)[0];
    },
    getHeaderCols() {
      return document.getElementsByClassName(this.classObject.headerCol);
    },
    getBodyRows() {
      return document.getElementsByClassName(this.classObject.bodyRow);
    },
    getBodyCols() {
      return document.getElementsByClassName(this.classObject.bodyCol);
    },
    refreshRowHeightStyle() {
      let height = this.getRowHeight() + "px";
      let tableHeader = this.getTableHeader();
      tableHeader.style.height = height;
      let bodyRows = this.getBodyRows();
      for (let i = 0; i < bodyRows.length; i++) {
        bodyRows[i].style.height = height;
      }
      let headerCols = this.getHeaderCols();
      for (let i = 0; i < headerCols.length; i++) {
        headerCols[i].style.height = height;
        headerCols[i].style.lineHeight = height;
      }
      let bodyCols = this.getBodyCols();
      for (let i = 0; i < bodyCols.length; i++) {
        bodyCols[i].style.height = height;
        bodyCols[i].style.lineHeight = height;
      }
    },
    refreshHeaderStyle() {
      let headerCols = this.getHeaderCols();
      for (let i = 0; i < headerCols.length; i++) {
        headerCols[i].style.color = this.widget.option.header.color;
        headerCols[i].style.fontSize =
          this.widget.option.header.fontSize + "px";
        headerCols[i].style.fontWeight = this.widget.option.header.fontWeight;
        headerCols[i].style.backgroundColor =
          this.widget.option.header.backgroundColor;
      }
    },
    refreshBodyStyle() {
      let bodyRows = this.getBodyRows();
      for (let i = 0; i < bodyRows.length; i++) {
        const bodyCols = bodyRows[i].children;
        for (let j = 0; j < bodyCols.length; j++) {
          bodyCols[j].style.color = this.widget.option.body.color;
          bodyCols[j].style.fontSize = this.widget.option.body.fontSize + "px";
          bodyCols[j].style.fontWeight = this.widget.option.body.fontWeight;
          if (i % 2 === 0) {
            bodyCols[j].style.backgroundColor =
              this.widget.option.body.evenBackgroundColor;
          } else {
            bodyCols[j].style.backgroundColor =
              this.widget.option.body.oddBackgroundColor;
          }
        }
      }
    },
    refreshTableBorderStyle() {
      let headerCols = this.getHeaderCols();
      for (let i = 0; i < headerCols.length; i++) {
        headerCols[i].style.borderRight =
          "1px solid " + this.widget.option.borderColor;
      }
      let bodyCols = document.getElementsByClassName(this.classObject.bodyCol);
      for (let i = 0; i < bodyCols.length; i++) {
        bodyCols[i].style.borderTop =
          "1px solid " + this.widget.option.borderColor;
        bodyCols[i].style.borderRight =
          "1px solid " + this.widget.option.borderColor;
      }
    },
    getRowHeight() {
      return this.widget.location.height / (this.widget.option.rowNumber + 1);
    },
    getTranslateY(translateY) {
      if (!translateY) {
        return 0;
      }
      return Number(
        translateY.substring(
          translateY.indexOf("(") + 1,
          translateY.indexOf("px")
        )
      );
    },
    startScrollTableTimer() {
      this.clearScrollTimer();
      if (this.widget.option.scroll.enable) {
        this.scrollTimer = setInterval(() => {
          if (
            this.widget.option.body.data.length > this.widget.option.rowNumber
          ) {
            this.scrollTableRow();
          } else {
            this.recoveryTableData();
          }
        }, this.widget.option.scroll.time);
      }
    },
    recoveryTableData() {
      this.firstRow = 0;
      let bodyRows = this.getBodyRows();
      for (let i = 0; i < bodyRows.length; i++) {
        bodyRows[i].style.transform = "translateY(0px)";
      }
    },
    recoveryRenderObject() {
      if (this.render && this.render.apiTimer) {
        clearInterval(this.render.apiTimer);
        this.render.apiTimer = null;
      }
      if(this.render && this.render.websocket) {
        this.render.websocket.doDisconnect();
      }
    },
    clearScrollTimer() {
      if (this.scrollTimer) {
        clearInterval(this.scrollTimer);
        this.scrollTimer = null;
        this.recoveryTableData();
      }
    },
    scrollTableRow() {
      let height = this.getRowHeight();
      let length = this.widget.option.body.data.length;
      let bodyRows = this.getBodyRows();
      for (let i = 0; i < bodyRows.length; i++) {
        let translateY =
          this.getTranslateY(bodyRows[i].style.transform) - height;
        if (i === this.firstRow) {
          translateY = height * (length - i - 1);
        }
        bodyRows[i].style.transform = "translateY(" + translateY + "px)";
      }
      // 重新计算第一个表格行在数组的下标值
      if (this.firstRow === length - 1) {
        this.firstRow = 0;
      } else {
        this.firstRow += 1;
      }
    },
  },
};
</script>
<style lang="stylus">
.data-table {
  box-sizing: border-box;
  overflow: hidden;

  .table-header {
    height: 100%;

    .header-col {
      height: 100%;
      color: #ffffff;
      display: inline-block;
      vertical-align: top;
      box-sizing: border-box;
      overflow: hidden;
      text-align: center;

      &:last-child {
        border-right: none !important;
      }
    }
  }

  .table-body {
    overflow: hidden;

    .body-row {
      transition: all 0.5s;

      .body-col {
        height: 100%;
        color: #ffffff;
        display: inline-block;
        vertical-align: top;
        box-sizing: border-box;
        overflow: hidden;
        text-align: center;

        &:last-child {
          border-right: none !important;
        }
      }
    }
  }
}
</style>

